<template>
    <el-card class="network-monitor">
      <template #header>
        <div class="card-header">
          <span>网络监控</span>
          <div class="action-buttons">
            <el-button 
              type="primary" 
              size="small" 
              @click="startMonitoring" 
              :disabled="isMonitoring"
              :loading="isStarting"
            >
              {{ isMonitoring ? '监控中...' : '开始监控' }}
            </el-button>
            <el-button 
              type="danger" 
              size="small" 
              @click="stopMonitoring" 
              :disabled="!isMonitoring"
            >
              停止监控
            </el-button>
            <el-tooltip content="刷新节点列表" placement="top">
              <el-button 
                type="info" 
                size="small" 
                @click="refreshNodes"
                :loading="isRefreshing"
                circle
              >
                <el-icon><Refresh /></el-icon>
              </el-button>
            </el-tooltip>
          </div>
        </div>
      </template>
      
      <div class="monitor-content">
        <el-table 
          :data="nodes" 
          style="width: 100%"
          v-loading="isChecking"
          stripe
          border
          highlight-current-row
        >
          <el-table-column prop="name" label="节点名称" width="150" sortable></el-table-column>
          <el-table-column prop="ip" label="IP地址" width="150" sortable></el-table-column>
          <el-table-column label="网络状态" width="120" sortable>
            <template #default="{row}">
              <el-tag :type="getStatusTagType(row.networkStatus)" effect="dark">
                {{ getStatusText(row.networkStatus) }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="当前延迟(ms)" width="120" sortable :sort-method="sortNumber('latency')">
            <template #default="{row}">
              <span :class="getLatencyClass(row.latency)">
                {{ formatLatency(row.latency) }}
              </span>
            </template>
          </el-table-column>
          <el-table-column label="最小延迟(ms)" width="120" sortable :sort-method="sortNumber('minLatency')">
            <template #default="{row}">
              {{ formatLatency(row.minLatency) }}
            </template>
          </el-table-column>
          <el-table-column label="最大延迟(ms)" width="120" sortable :sort-method="sortNumber('maxLatency')">
            <template #default="{row}">
              <span :class="getLatencyClass(row.maxLatency, true)">
                {{ formatLatency(row.maxLatency) }}
              </span>
            </template>
          </el-table-column>
          <el-table-column label="平均延迟(ms)" width="120" sortable :sort-method="sortNumber('avgLatency')">
            <template #default="{row}">
              {{ formatLatency(row.avgLatency) }}
            </template>
          </el-table-column>
          <el-table-column label="丢包率" width="100" sortable :sort-method="sortNumber('packetLoss')">
            <template #default="{row}">
              <span :class="getPacketLossClass(row.packetLoss)">
                {{ formatPacketLoss(row.packetLoss) }}
              </span>
            </template>
          </el-table-column>
          <el-table-column label="最后检测时间" width="180" prop="lastCheck" sortable>
            <template #default="{row}">
              {{ row.lastCheck || '-' }}
            </template>
          </el-table-column>
        </el-table>
          
        <div class="alerts-container">
          <div class="alerts-header">
            <h3>实时报警 ({{ realtimeAlerts.length }})</h3>
            <div class="alert-actions">
              <el-switch
                v-model="enableSound"
                active-text="声音报警"
                inactive-text="静音"
              />
              <el-button 
                size="small" 
                @click="clearAlerts"
                :disabled="realtimeAlerts.length === 0"
              >
                清空报警
              </el-button>
            </div>
          </div>
          <div class="alerts-list">
            <div 
              v-for="alert in realtimeAlerts" 
              :key="alert.id" 
              class="alert-item" 
              :class="alert.level"
            >
              <div class="alert-time">{{ formatTime(alert.timestamp) }}</div>
              <div class="alert-content">{{ alert.message }}</div>
              <el-icon class="alert-close" @click="removeAlert(alert.id)"><Close /></el-icon>
            </div>
            <div v-if="realtimeAlerts.length === 0" class="empty-alerts">
              <el-empty description="暂无报警信息" :image-size="60" />
            </div>
          </div>
        </div>
      </div>
    </el-card>
  </template>
  
  <script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { ElMessage, ElNotification } from 'element-plus'
import { Refresh, Close } from '@element-plus/icons-vue'
import request from '@/utils/request'
import { EventSourcePolyfill } from 'event-source-polyfill'

// 状态数据
const nodes = ref([])
const realtimeAlerts = ref([])
const isMonitoring = ref(false)
const isStarting = ref(false)
const isChecking = ref(false)
const isRefreshing = ref(false)
const enableSound = ref(true)
let eventSource = null
let checkInterval = null

// 常量定义
const LATENCY_THRESHOLDS = {
  good: 50,
  warning: 100,
  danger: 200
}

const PACKET_LOSS_THRESHOLDS = {
  good: 1,
  warning: 5,
  danger: 10
}

// 辅助函数
const formatTime = (timestamp) => {
  return new Date(timestamp * 1000).toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false
  }).replace(/\//g, '-')
}

const getStatusTagType = (status) => {
  const map = {
    online: 'success',
    offline: 'danger',
    error: 'info'
  }
  return map[status] || 'info'
}

const getStatusText = (status) => {
  const map = {
    online: '在线',
    offline: '离线',
    error: '错误'
  }
  return map[status] || status
}

const formatLatency = (value) => {
  return value !== null && value !== undefined ? Number(value).toFixed(2) : '-'
}

const formatPacketLoss = (value) => {
  if (value === null || value === undefined) return '-'
  return value === 0 ? '0%' : `${Number(value).toFixed(2)}%`
}

const getLatencyClass = (value, isMax = false) => {
  if (value === null || value === undefined) return ''
  const num = Number(value)
  if (isMax && num > LATENCY_THRESHOLDS.danger) return 'latency-danger'
  if (num > LATENCY_THRESHOLDS.warning) return 'latency-warning'
  if (num > LATENCY_THRESHOLDS.good) return 'latency-good'
  return 'latency-optimal'
}

const getPacketLossClass = (value) => {
  if (value === null || value === undefined) return ''
  const num = Number(value)
  if (num >= PACKET_LOSS_THRESHOLDS.danger) return 'packet-loss-danger'
  if (num >= PACKET_LOSS_THRESHOLDS.warning) return 'packet-loss-warning'
  if (num > PACKET_LOSS_THRESHOLDS.good) return 'packet-loss-good'
  return 'packet-loss-optimal'
}

const sortNumber = (prop) => (a, b) => {
  const valA = a[prop] === null ? Infinity : Number(a[prop])
  const valB = b[prop] === null ? Infinity : Number(b[prop])
  return valA - valB
}

// 播放报警声音
const playAlertSound = () => {
  if (enableSound.value) {
    const audio = new Audio('/static/alert.mp3')
    audio.play().catch(e => console.warn('播放声音失败:', e))
  }
}

// 获取节点列表
const fetchNodes = async () => {
  try {
    const res = await request.get('/api/nodes')
    nodes.value = res.data.items.map(node => ({
      ...node,
      networkStatus: node.networkStatus || 'unknown',
      latency: node.latency || null,
      minLatency: node.minLatency || null,
      maxLatency: node.maxLatency || null,
      avgLatency: node.avgLatency || null,
      packetLoss: node.packetLoss || null,
      lastCheck: node.lastCheck ? formatTime(node.lastCheck) : null
    }))
  } catch (error) {
    ElMessage.error('获取节点列表失败')
    console.error('获取节点列表失败:', error)
  }
}

// 刷新节点列表
const refreshNodes = async () => {
  isRefreshing.value = true
  try {
    await fetchNodes()
    ElMessage.success('节点列表已刷新')
  } catch (error) {
    console.error('刷新节点列表失败:', error)
  } finally {
    isRefreshing.value = false
  }
}

// 开始监控
const startMonitoring = async () => {
  if (isMonitoring.value) return

  isStarting.value = true
  try {
    const token = localStorage.getItem('token')
    eventSource = new EventSourcePolyfill('http://localhost:5000/stream/network-alerts', {
      headers: {
        'Authorization': `Bearer ${token}`
      },
      withCredentials: true,  // 必须设置为true
      heartbeatTimeout: 60000 // 心跳超时设置
    })

    eventSource.onmessage = (event) => {
      const data = JSON.parse(event.data)
      if (data.type === 'network-alert') {
        const newAlert = {
          id: Date.now(),
          timestamp: data.timestamp,
          message: `${data.message} (节点ID: ${data.node_id}, IP: ${data.node_ip})`,
          level: data.level || 'warning'
        }

        realtimeAlerts.value.unshift(newAlert)

        if (data.level === 'critical') {
          ElNotification.error({
            title: '严重报警',
            message: newAlert.message,
            duration: 0
          })
          playAlertSound()
        } else if (data.level === 'warning') {
          ElNotification.warning({
            title: '警告',
            message: newAlert.message,
            duration: 5000
          })
        }

        if (realtimeAlerts.value.length > 100) {
          realtimeAlerts.value.pop()
        }
      }
    }

    eventSource.onerror = (error) => {
      console.error('SSE连接错误:', error)
      setTimeout(startMonitoring, 5000)
    }

    isMonitoring.value = true
    ElMessage.success('已开始网络监控')

    await checkNetworkStatus()
    checkInterval = setInterval(checkNetworkStatus, 30000)
  } catch (error) {
    ElMessage.error('启动监控失败')
    console.error('启动监控失败:', error)
  } finally {
    isStarting.value = false
  }
}

// 检测网络状态
const checkNetworkStatus = async () => {
  if (!isMonitoring.value) return

  isChecking.value = true
  try {
    const res = await request.post('/api/network/check')
    if (res.status === 'success' && res.data) {
      nodes.value = nodes.value.map(node => {
        const nodeStatus = res.data.find(n => n.node_id === node.id)
        return nodeStatus ? {
          ...node,
          networkStatus: nodeStatus.status,
          latency: nodeStatus.latency ?? null,
          minLatency: nodeStatus.min_latency ?? null,
          maxLatency: nodeStatus.max_latency ?? null,
          avgLatency: nodeStatus.avg_latency ?? null,
          packetLoss: nodeStatus.packet_loss ?? null,
          lastCheck: nodeStatus.last_check ? formatTime(nodeStatus.last_check) : null
        } : node
      })
    } else if (res.status === 'success' && res.data.task_id) {
      ElMessage.info('网络检测任务已启动，请稍后刷新')
    }
  } catch (error) {
    console.error('网络检测失败:', error)
    ElMessage.warning('网络检测失败，5秒后重试')
  } finally {
    isChecking.value = false
  }
}

// 停止监控
const stopMonitoring = () => {
  if (eventSource) {
    eventSource.close()
    eventSource = null
  }

  if (checkInterval) {
    clearInterval(checkInterval)
    checkInterval = null
  }

  isMonitoring.value = false
  nodes.value = nodes.value.map(node => ({
    ...node,
    networkStatus: 'unknown',
    latency: null,
    minLatency: null,
    maxLatency: null,
    avgLatency: null,
    packetLoss: null,
    lastCheck: null
  }))

  ElMessage.info('已停止网络监控')
}

// 报警管理
const removeAlert = (id) => {
  const index = realtimeAlerts.value.findIndex(a => a.id === id)
  if (index !== -1) {
    realtimeAlerts.value.splice(index, 1)
  }
}

const clearAlerts = () => {
  realtimeAlerts.value = []
  ElMessage.success('已清空报警列表')
}

onMounted(() => {
  fetchNodes()
})

onUnmounted(() => {
  stopMonitoring()
})
</script>
  
  <style scoped>
  .network-monitor {
    margin: 20px;
  }
  
  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  
  .action-buttons {
    display: flex;
    gap: 8px;
  }
  
  .monitor-content {
    margin-top: 20px;
  }
  
  .alerts-container {
    margin-top: 30px;
  }
  
  .alerts-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
  }
  
  .alert-actions {
    display: flex;
    align-items: center;
    gap: 12px;
  }
  
  .alerts-list {
    max-height: 400px;
    overflow-y: auto;
    border: 1px solid var(--el-border-color);
    border-radius: 4px;
    min-height: 100px;
  }
  
  .alert-item {
    position: relative;
    padding: 12px;
    border-bottom: 1px solid var(--el-border-color);
    transition: all 0.3s;
  }
  
  .alert-item:hover {
    background-color: var(--el-fill-color-light);
  }
  
  .alert-item.critical {
    background-color: var(--el-color-danger-light-9);
    border-left: 3px solid var(--el-color-danger);
  }
  
  .alert-item.warning {
    background-color: var(--el-color-warning-light-9);
    border-left: 3px solid var(--el-color-warning);
  }
  
  .alert-item.info {
    background-color: var(--el-color-info-light-9);
    border-left: 3px solid var(--el-color-info);
  }
  
  .alert-time {
    font-size: 12px;
    color: var(--el-text-color-secondary);
  }
  
  .alert-content {
    margin-top: 5px;
    font-size: 14px;
  }
  
  .alert-close {
    position: absolute;
    right: 10px;
    top: 10px;
    cursor: pointer;
    color: var(--el-text-color-secondary);
    font-size: 14px;
  }
  
  .alert-close:hover {
    color: var(--el-color-primary);
  }
  
  .empty-alerts {
    padding: 20px;
    text-align: center;
    color: var(--el-text-color-secondary);
  }
  
  /* 延迟样式 */
  .latency-optimal {
    color: var(--el-color-success);
  }
  .latency-good {
    color: var(--el-color-info);
  }
  .latency-warning {
    color: var(--el-color-warning);
  }
  .latency-danger {
    color: var(--el-color-danger);
    font-weight: bold;
  }
  
  /* 丢包率样式 */
  .packet-loss-optimal {
    color: var(--el-color-success);
  }
  .packet-loss-good {
    color: var(--el-color-info);
  }
  .packet-loss-warning {
    color: var(--el-color-warning);
  }
  .packet-loss-danger {
    color: var(--el-color-danger);
    font-weight: bold;
  }
  </style>